﻿using UnityEngine;
using System.Extension;
namespace System.Reflection.Extension
{
    public static class MemberInfoExtension
    {
        public static void ForEachAttribute(this MemberInfo memberInfo, Action<Attribute> callBack)
        {
            object[] attributes = memberInfo.GetCustomAttributes(true);
            foreach (Attribute attribute in attributes)
                callBack(attribute);
        }

        public static Type GetMemberType(this MemberInfo memberInfo)
        {
            Type type = null;
            if (memberInfo.MemberType == MemberTypes.Field)
                type = ((FieldInfo)memberInfo).FieldType;
            else if (memberInfo.MemberType == MemberTypes.Property)
                type = ((PropertyInfo)memberInfo).PropertyType;
            return type;
        }

        public static object GetValue(this MemberInfo memberInfo, object obj)
        {
            object val = null;
            if (memberInfo.MemberType == MemberTypes.Field)
                val = ((FieldInfo)memberInfo).GetValue(obj);
            else if (memberInfo.MemberType == MemberTypes.Property)
                val = ((PropertyInfo)memberInfo).GetValue(obj, null);
            return val;
        }

        public static void SetValue(this MemberInfo memberInfo, object obj, object val) // type conversion requires
        {
            if (memberInfo.MemberType == MemberTypes.Field)
            {
                FieldInfo fieldInfo = (FieldInfo)memberInfo;
                fieldInfo.SetValue(obj, val);
            }
            else if (memberInfo.MemberType == MemberTypes.Property)
            {
                PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
                if (propertyInfo.CanWrite)
                {
                    //Debug.Log("Member :" + memberInfo.Name);
                    propertyInfo.SetValue(obj, val, null);
                }
            }
        }

        public static bool isInclusive(this MemberInfo member, params Type[] inclusives)
        {
            bool result = false;
            if (member.isNotNull())
            {
                if (member.MemberType == MemberTypes.Field)
                    result = ((FieldInfo)member).isInclusive(inclusives);
                else if (member.MemberType == MemberTypes.Property)
                    result = ((PropertyInfo)member).isInclusive(inclusives);
            }
            return result;
        }
        public static bool isPrimitive(this MemberInfo member)
        {
            bool result = false;
            if (member.isNotNull())
            {
                if (member.MemberType == MemberTypes.Field)
                    result = ((FieldInfo)member).isPrimitive();
                else if (member.MemberType == MemberTypes.Property)
                    result = ((PropertyInfo)member).isPrimitive();
            }
            return result;
        }

        public static bool HasAttribute<T>(this MemberInfo member) where T :Attribute
        {
            bool result = false;
            if (member.MemberType == MemberTypes.Field)
                result = ((FieldInfo)member).HasAttribute<T>();
            else if (member.MemberType == MemberTypes.Property)
                result = ((PropertyInfo)member).HasAttribute<T>();
            return result;
        }

        public static bool isClass(this MemberInfo member)
        {
            bool result = false;
            if (member.MemberType == MemberTypes.Field)
                result = ((FieldInfo)member).isClass();
            else if (member.MemberType == MemberTypes.Property)
                result = ((PropertyInfo)member).isClass();
            return result;
        }
        public static bool IsValueType(this MemberInfo member)
        {
            bool result = false;
            if (member.MemberType == MemberTypes.Field)
                result = ((FieldInfo)member).IsValueType();
            else if (member.MemberType == MemberTypes.Property)
                result = ((PropertyInfo)member).IsValueType();
            return result;
        }
        public static bool isGeneric(this MemberInfo member)
        {
            bool result = false;
            if (member.MemberType == MemberTypes.Field)
                result = ((FieldInfo)member).isGeneric();
            else if (member.MemberType == MemberTypes.Property)
                result = ((PropertyInfo)member).isGeneric();
            return result;
        }

        public static bool isEnum(this MemberInfo member)
        {
            bool result = false;
            if (member.MemberType == MemberTypes.Field)
                result = ((FieldInfo)member).FieldType.IsEnum;
            else if (member.MemberType == MemberTypes.Property)
                result = ((PropertyInfo)member).PropertyType.IsEnum;
            return result;
        }

        public static bool IsSameOrSubclass(this MemberInfo member, Type baseType)
        {
            bool result = false;
            Type memberType = member.GetMemberType();
            result = memberType.IsSubclassOf(baseType) || memberType == baseType;
            return result;
        }

    }
}
